package com.flute.haflute.tools;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;

import com.flute.haflute.common.SerializerInterface;
import com.flute.haflute.net.messaging.Message;

/**
 * 普通工具类
 */
public class Utils {

	/**
	 * 向Session发送Message消息，该方法的作用在于统一集群消息发送的流程，避免消息处理格式错误。
	 * 
	 * @param session
	 *            org.apache.mina.core.session.IoSession
	 * @param message
	 *            com.flute.haflute.net.messaging.Message
	 * @throws IOException
	 */
	public static void sendMessage(IoSession session, Message message)
			throws IOException {
		session.write(getIoBufferOfObject(message, Message.serializer()));
	}

	/**
	 * 将对象序列化处理成org.apache.mina.core.buffer.IoBuffer的方法
	 * 
	 * @see getBytesOfObject
	 */
	public static <T> IoBuffer getIoBufferOfObject(T t,
			SerializerInterface<T> serializer) throws IOException {
		IoBuffer buffer = IoBuffer.wrap(getBytesOfObject(t, serializer));
		return buffer;
	}

	/**
	 * 将对象序列化处理成字节流的方法
	 * 
	 * @param <T>
	 * @param t
	 *            需要进行序列化处理的对象
	 * @param serializer
	 *            为类型为T的对象进行序列化的处理者
	 * @return
	 * @throws IOException
	 */
	public static <T> byte[] getBytesOfObject(T t,
			SerializerInterface<T> serializer) throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(bos);
		serializer.serialize(t, dos);
		return bos.toByteArray();
	}

	public static int bytes2int(byte[] b) {
		int mask = 0xff;
		int temp = 0;
		int res = 0;
		for (int i = 0; i < 4; i++) {
			res <<= 8;
			temp = b[i] & mask;
			res |= temp;
		}
		return res;
	}

	public static byte[] int2bytes(int num) {
		byte[] b = new byte[4];
		for (short i = 0; i < 4; i++) {
			b[i] = (byte) (num >> (24 - i * 8));
		}
		return b;
	}

	public static <T extends Serializable> byte[] serialize(T obj)
			throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(bos);
		oos.writeObject(obj);
		return bos.toByteArray();
	}

	@SuppressWarnings("unchecked")
	public static <T extends Serializable> T deserialize(byte[] bytes)
			throws IOException, ClassNotFoundException {
		ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
		ObjectInputStream ois = new ObjectInputStream(bis);
		T obj = (T) ois.readObject();
		return obj;
	}
}
